package com.coocaa.x.service.litecontent.providers.apps;

import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.os.RemoteException;

import com.coocaa.x.framework.utils.Android;
import com.coocaa.x.framework.utils.AsyncTask;
import com.coocaa.x.framework.utils.Cache;
import com.coocaa.x.framework.utils.LogUtils;
import com.coocaa.x.provider.xprovider.XProviderManager;
import com.coocaa.x.service.XServiceManager;
import com.coocaa.x.service.litecontent.BroadcastAction;
import com.coocaa.x.service.litecontent.data.apps.com_coocaa_app.AppData;
import com.coocaa.x.service.litecontent.providers.DataResolver;
import com.coocaa.x.service.litecontent.providers.apps.controller.AppLastStartTimesDataController;
import com.coocaa.x.service.litecontent.providers.apps.controller.AppStartTimesDataController;
import com.coocaa.x.service.litepm.data.AppInfo;
import com.coocaa.x.service.litepm.data.MActivityInfo;
import com.skyworth.logsdk.appstore.LogAPIForAppStore;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.ReentrantLock;

public class LocalAppManager {
    private static final String tag = "lam";
    private static ReentrantLock lock = new ReentrantLock();
    private static LocalAppManager instance = null;
    private static Context mContext = null;
    //    private Cache<String, AppData> installedApps = new Cache<String, AppData>();
    private AppDataResolver mAppDataResolver = null;

    public enum AppAction {
        APP_ADD,
        APP_REMOVE,
        SDCARD_CHANGED
    }

    public static synchronized LocalAppManager getInstance() {
        return instance;
    }

    public static synchronized void create(Context context) {
        if (instance == null)
            instance = new LocalAppManager(context);
    }

    private LocalAppManager(Context context) {
        mContext = context;
        registerBroastCast(context);
        mAppDataResolver = new AppDataResolver();
        mAppDataResolver.getData(null);
    }


    BroadcastReceiver mInstalledReceiver = new BroadcastReceiver() {

        @Override
        public void onReceive(Context arg0, final Intent intent) {
            LogUtils.d(tag, "mInstalledReceiver has app installed  or uninstalled  !! action:" + intent.getAction());
            AsyncTask.runOnThread(new Runnable() {

                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    String action = intent.getAction();
                    String pkgName = intent.getDataString().substring(8);
                    if (action.equals("android.intent.action.PACKAGE_ADDED")) {
                        AppData data = getInstalledAppData(pkgName);
                        if (data.info != null && data.info.pkgName != null && !data.info.pkgName.equals("") && !data.info.pkgName.equals("com.coocaa.x.app.hall")) {
                            LogUtils.d(tag, "install  pkg:" + data.info.pkgName);
//                            installedApps.add(pkgName, data);
                            mAppDataResolver.getData(null).add(pkgName, data);
                            LogAPIForAppStore.appStatus(0, data.info.pkgName, "安装成功");
                            //广播出去，有应用安装了
                            sendBroadcast(AppAction.APP_ADD.toString(), new String[]{pkgName});
                        }
                        disableCompletedReceiver(pkgName);
                        LogUtils.d(tag, "add  size:" + mAppDataResolver.getData(null).size());

                    }
                    if (action.equals("android.intent.action.PACKAGE_REMOVED")) {
                        mAppDataResolver.getData(null).remove(pkgName);
                        LogAPIForAppStore.appStatus(0, pkgName, "卸载成功");
                        LogUtils.d(tag, "remove  size:" + mAppDataResolver.getData(null).size());
                        //广播出去，有应用卸载了
                        sendBroadcast(AppAction.APP_REMOVE.toString(), new String[]{pkgName});
                    }
                }
            });
        }
    };

    private BroadcastReceiver sdcardReceiver = new BroadcastReceiver() {

        @Override
        public void onReceive(Context arg0, final Intent intent) {
            AsyncTask.runOnThread(new Runnable() {

                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    String action = intent.getAction();
                    final String[] packages = intent
                            .getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
                    if (action.equals(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE)) {
                        if (packages.length > 0) {
                            for (String pkg : packages) {
                                LogUtils.d("test", "sdcardReceiver  pkg:" + pkg);
                            }
                        }
                        int oldSize = mAppDataResolver.getData(null).size();
                        mAppDataResolver.loadInstalledApps(false);
                        int newSize = mAppDataResolver.getData(null).size();
                        LogUtils.d("test", "sdcardReceiver  available size:" + oldSize
                                + " newsize:" + newSize);
                        //广播出去
                        sendBroadcast(AppAction.SDCARD_CHANGED.toString(), packages);
                    } else if (action.equals(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE)) {
                        int oldSize = mAppDataResolver.getData(null).size();
                        mAppDataResolver.loadInstalledApps(false);
                        int newSize = mAppDataResolver.getData(null).size();
                        LogUtils.d("test", "sdcardReceiver  unavailable size:" + oldSize
                                + " newsize:" + newSize);
                        //广播出去
                        sendBroadcast(AppAction.SDCARD_CHANGED.toString(), packages);
                    }
                }
            });
        }
    };

    private BroadcastReceiver startAppReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String pkg = intent.getStringExtra("pkg");
            LogUtils.d(tag, "startAppReceiver  pkg:" + pkg);
            if (pkg != null && !pkg.equals("")) {
                AppStartTimesDataController.getInstance().insert(pkg);
                AppLastStartTimesDataController.getInstance().insert(pkg);
            }
        }
    };

    private void registerBroastCast(Context mContext) {
        LogUtils.i(tag, "registerBroastCast");
        IntentFilter installFilter = new IntentFilter();
        installFilter.addAction("android.intent.action.PACKAGE_ADDED");
        installFilter.addAction("android.intent.action.PACKAGE_REMOVED");
        installFilter.addDataScheme("package");
        mContext.registerReceiver(mInstalledReceiver, installFilter);

        IntentFilter filter2 = new IntentFilter();
        filter2.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
        filter2.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
        mContext.registerReceiver(sdcardReceiver, filter2);

        IntentFilter filter3 = new IntentFilter();
        filter3.addAction(BroadcastAction.APPSTARTBROASTCAST);
        mContext.registerReceiver(startAppReceiver, filter3);
    }

    private void unregisterBroacast() {
        LogUtils.i(tag, "unregisterBroacast");
        mContext.unregisterReceiver(mInstalledReceiver);
        mContext.unregisterReceiver(sdcardReceiver);
        mContext.unregisterReceiver(startAppReceiver);
    }

    private void disableCompletedReceiver(String pkg)
    {
        List<ComponentName> list = Android.getCOMPLETEDComponentNamesByPkg(mContext,pkg);
        if(list.size() > 0)
        {
            for(ComponentName cn:list) {
                LogUtils.d("completed","disableCompletedReceiver  pkg:"+cn.getPackageName()+" activity:"+cn.getClassName());
                Android.setComponentEnabledSetting(mContext, cn, PackageManager.COMPONENT_ENABLED_STATE_DISABLED);
            }
        }
    }

    private ArrayList<String> getChangedPkgList(List<String> bigList, List<String> smallList) {
        ArrayList<String> changeList = new ArrayList<String>();
        if (smallList != null && smallList.size() > 0 && bigList != null && bigList.size() > 0) {
            for (String pkg : bigList) {
                if (!smallList.contains(pkg)) {
                    changeList.add(pkg);
                    LogUtils.d("lam1", "getChangedPkgList  pkg:" + pkg);
                }
            }
        }
        return changeList;
    }

    private void sendBroadcast(String action, String[] pkgArray) {
        Intent i = new Intent();
        i.setAction(BroadcastAction.APPCHANGEDBROASTCAST);
        i.putExtra("action", action);
        i.putExtra("extra", pkgArray);
        mContext.sendBroadcast(i);
        LogUtils.d("web", "sendBroadcast!!");
    }

    public void onDestory() {
        unregisterBroacast();
    }


    public List<AppData> getInstalledAppList() {
        LogUtils.d(tag, "getInstalledAppList ## size:" + mAppDataResolver.getData(null).size());
        return mAppDataResolver.getData(null).values();
    }

    public Cache<String, AppData> getListCache() {
        return mAppDataResolver.getData(null);
    }

    public AppData getAppData(String pkgname) {
        return mAppDataResolver.getData(null).get(pkgname);
    }

    private AppData getInstalledAppData(AppInfo info) {
        AppData appData = new AppData();
        appData.info = info;
        appData.usedTimes = AppStartTimesDataController.getInstance().getAppStartTimes(info.pkgName);
        appData.recentlyUsedTimes = AppLastStartTimesDataController.getInstance()
                .getRecentlyUsedTimes(info.pkgName);
        return appData;
    }

    private AppData getInstalledAppData(String pkg) {
        LogUtils.d(tag, "getInstalledAppData pkg:" + pkg);
        PackageManager pm = mContext.getPackageManager();
        Intent intent = new Intent(Intent.ACTION_MAIN, null);
        intent.addCategory(Intent.CATEGORY_LAUNCHER);
        intent.setPackage(pkg);
        List<ResolveInfo> resolveInfo = pm.queryIntentActivities(intent, PackageManager.GET_DISABLED_COMPONENTS);
        if (resolveInfo != null && resolveInfo.size() > 0) {
            AppData appData = new AppData();
            AppInfo mAppInfo = new AppInfo();
            ResolveInfo info = resolveInfo.get(0);
            List<MActivityInfo> list = new ArrayList<MActivityInfo>();
            if ((info.activityInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0 || pkg.equals("com.tianci.appstore"))
                mAppInfo.isSystemApp = true;
            mAppInfo.pkgName = info.activityInfo.packageName;
//            mAppInfo.appName = info.loadLabel(mContext.getPackageManager()).toString();
            mAppInfo.mainActivity = info.activityInfo.name;
            for (ResolveInfo rInfo : resolveInfo) {
                MActivityInfo aInfo = new MActivityInfo();
                aInfo.pkg = rInfo.activityInfo.packageName;
                aInfo.className = rInfo.activityInfo.name;
                aInfo.name = rInfo.loadLabel(mContext.getPackageManager()).toString();
                LogUtils.d(tag, "pkg:" + info.activityInfo.packageName + " name:" + aInfo.name
                        + " className:" + aInfo.className);
                list.add(aInfo);
            }

            mAppInfo.activityList = list;
            try {
                PackageInfo packageInfo = mContext.getPackageManager().getPackageInfo(
                        info.activityInfo.packageName, 0);
                mAppInfo.appName = packageInfo.applicationInfo.loadLabel(mContext.getPackageManager()).toString();
                mAppInfo.versionName = packageInfo.versionName;
                mAppInfo.versionCode = packageInfo.versionCode;
                mAppInfo.firstInstallTime = packageInfo.firstInstallTime;
                if (packageInfo.sharedUserId != null && packageInfo.sharedUserId.equals("android.uid.system")) {
                    mAppInfo.isSystemUserId = true;
                } else {
                    mAppInfo.isSystemUserId = false;
                }
            } catch (NameNotFoundException e) {
                e.printStackTrace();
            }
            mAppInfo.size = new File(info.activityInfo.applicationInfo.publicSourceDir).length();
            appData.usedTimes = AppStartTimesDataController.getInstance().getAppStartTimes(pkg);
            appData.recentlyUsedTimes = AppLastStartTimesDataController.getInstance()
                    .getRecentlyUsedTimes(pkg);
            appData.info = mAppInfo;
            return appData;
        }
        return new AppData();
    }


    public void updateAppStartTimes(String pkg) {
        AppData data = mAppDataResolver.getData(null).get(pkg);
        if (data != null) {
            data.recentlyUsedTimes = AppLastStartTimesDataController.getInstance().getRecentlyUsedTimes(pkg);
            data.recentlyUsedTimes = AppStartTimesDataController.getInstance().getAppStartTimes(pkg);
        }
    }


    class AppDataResolver extends DataResolver<Cache<String, AppData>, Object> {
        private Cache<String, AppData> installedApps = new Cache<String, AppData>();

        @Override
        protected Cache<String, AppData> getDataFromCache(Object o) {
            LogUtils.d(tag, "getDataFromCache...size:" + installedApps.size());
            if (installedApps.size() < 1)
                return null;
            return installedApps;
        }

        @Override
        protected void updateCache(Object o, Cache<String, AppData> data) {
            LogUtils.d(tag, "updateCache...");
            installedApps = data;
        }

        @Override
        protected Cache<String, AppData> getDataFromOriginal(Object o) {
            LogUtils.d(tag, "getDataFromOriginal...");
            loadInstalledApps(true);
            return installedApps;
        }

        private void loadInstalledApps(final boolean needCollect) {

            //     // BUG #56014 随机性我的应用中的所有应用无法点击进入，应用全部为空，但是图标是天赐系统默认的图片。
            // 估计是开机启动太早就去拿应用列表，那不完整，先打上这个补丁试试看效果。
//            if (needCollect) {
//                try {
//                    Thread.sleep(5000);
//                } catch (InterruptedException e1) {
//                    // TODO Auto-generated catch block
//                    e1.printStackTrace();
//                }
//            }
            synchronized (installedApps) {
                installedApps.clear();
                List<AppInfo> list = new ArrayList<AppInfo>();
                try {
                    list = XServiceManager.getLitePMService().getInstalledApps();
                    if (list != null)
                        LogUtils.d(tag, "loadInstalledApps from pm ################  list size:" + list.size());
                } catch (RemoteException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                    LogUtils.d(tag, "loadInstalledApps from pm ################  error:");
                }

                List<Object> listPkg = XProviderManager.getBlackList();
//                if(listPkg != null && listPkg.size() > 0)
//                {
//                    LogUtils.d(tag,"listPkg  size:"+listPkg.size());
//                }

                if (list != null && list.size() > 0) {
                    for (AppInfo info : list) {
                        AppData data = getInstalledAppData(info);
                        if (data != null && !data.info.pkgName.equals("") && !data.info.pkgName.equals("com.coocaa.x.app.hall")) {
                            if(listPkg == null || listPkg.size() < 1 || !listPkg.contains(data.info.pkgName))
                            installedApps.add(data.info.pkgName, data);
                        }
                    }
                    LogUtils.d(tag, "loadInstalledApps  installedApps size:" + installedApps.size());
                }

                if (needCollect) {
                    List<String> pkgList = new ArrayList<String>();
                    for (AppData data2 : installedApps.values()) {
                        if (!data2.info.isSystemApp) {
//                            LogUtils.d(tag, "Collect pkg:" + data2.info.pkgName);
                            pkgList.add(data2.info.pkgName);
                        }
                    }
                    LogAPIForAppStore.appThirdPartyList(pkgList);
                }
            }

        }

    }

}
